
<!DOCTYPE html>
<html lang="en" data-figures="" class="page">
  <head>
<title>Docker | Alexzshl</title>
<meta charset="utf-8">
<meta name="generator" content="Hugo 0.80.0" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta property="og:locale" content="en" />

<meta property="og:type" content="article">
<meta name="description" content="Article description.">
<meta name="twitter:card" content="summary" />
<meta name="twitter:creator" content="">
<meta name="twitter:title" content="Docker" />
<meta property="og:url" content="https://alexzshl.gitee.io/blog/post/docker/" />
<meta property="og:title" content="Docker" />
<meta property="og:description" content="Article description." />
<meta property="og:image" content="https://alexzshl.gitee.io/blog/" />
<link rel="apple-touch-icon" sizes="180x180" href='https://alexzshl.gitee.io/blog/icons/apple-touch-icon.png'>
<link rel="icon" type="image/png" sizes="32x32" href='https://alexzshl.gitee.io/blog/icons/favicon-32x32.png'>
<link rel="manifest" href='https://alexzshl.gitee.io/blog/icons/site.webmanifest'>
<link rel="mask-icon" href='https://alexzshl.gitee.io/blog/safari-pinned-tab.svg' color="#002538">
<meta name="msapplication-TileColor" content="#002538">
<meta name="theme-color" content="#002538">

<link rel="canonical" href="https://alexzshl.gitee.io/blog/post/docker/">

    

    
    
    <link rel="preload" href="https://alexzshl.gitee.io/blog/css/styles.782bf96a82b3cc5b3cee4c47a42cc81321f16960a6d41fab3277c4abe047bc7ae044ea1bb7ae4d237c12baa0143e02f95969e5e8b6e68d9dcfd14158cfa244ac.css" integrity = "sha512-eCv5aoKzzFs87kxHpCzIEyHxaWCm1B&#43;rMnfEq&#43;BHvHrgROobt65NI3wSuqAUPgL5WWnl6LbmjZ3P0UFYz6JErA==" as="style" crossorigin="anonymous">
    <link rel="preload" href="https://alexzshl.gitee.io/blog/js/bundle.min.16ce52f0798f54d65cefb0a0fc9228cf99e0b73de57f8a1545fe14259265bf79ba12fe15afd2fd75d5f0bff8f416e8ca8c5c3458f87e014cbfbed8ccfdaee327.js" as="script" integrity=
    "sha512-Fs5S8HmPVNZc77Cg/JIoz5ngtz3lf4oVRf4UJZJlv3m6Ev4Vr9L9ddXwv/j0FujKjFw0WPh&#43;AUy/vtjM/a7jJw==" crossorigin="anonymous">

    
    <link rel="stylesheet" type="text/css" href="https://alexzshl.gitee.io/blog/css/styles.782bf96a82b3cc5b3cee4c47a42cc81321f16960a6d41fab3277c4abe047bc7ae044ea1bb7ae4d237c12baa0143e02f95969e5e8b6e68d9dcfd14158cfa244ac.css" integrity="sha512-eCv5aoKzzFs87kxHpCzIEyHxaWCm1B&#43;rMnfEq&#43;BHvHrgROobt65NI3wSuqAUPgL5WWnl6LbmjZ3P0UFYz6JErA==" crossorigin="anonymous">
    
  </head>
  
  
    
  
  <body data-code="100" data-lines="false" id="documentTop">

<header class="nav_header" >
  <nav class="nav">
    <a href='https://alexzshl.gitee.io/blog/' class="nav_brand nav_item">
        Alexzshl
      <div class="nav_close">
        <div>
          <svg class="icon">
  <use xlink:href="#open-menu"></use>
</svg>
          <svg class="icon">
  <use xlink:href="#closeme"></use>
</svg>
        </div>
      </div>
    </a>
    <div class='nav_body nav_body_'>
      
      
      
        

      
<div class='follow'>
<div class="color_mode">
  <input type="checkbox" class="color_choice" id="mode">
</div>

</div>

    </div>
  </nav>
</header>

    <main>
  
<div class="grid-inverse wrap content">
  <article class="post_content">
    <h1 class="post_title">Docker</h1><div class="post_meta">
  
    <svg class="icon">
  <use xlink:href="#calendar"></use>
</svg>
    <span class="post_date">
      Oct 6, 2020</span>
      <a href='https://alexzshl.gitee.io/blog/tags/docker' class="post_tag button button_translucent">docker
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/mysql' class="post_tag button button_translucent">mysql
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/nginx' class="post_tag button button_translucent">nginx
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/redis' class="post_tag button button_translucent">redis
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/elasticsearch' class="post_tag button button_translucent">elasticsearch
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/activemq' class="post_tag button button_translucent">ActiveMQ
      </a>
      <a href='https://alexzshl.gitee.io/blog/tags/docker-compose' class="post_tag button button_translucent">docker compose
      </a>
</div>

    
  <div class="post_share">
    Share on:
    <a href="https://twitter.com/intent/tweet?text=Docker&url=https%3a%2f%2falexzshl.gitee.io%2fblog%2fpost%2fdocker%2f&tw_p=tweetbutton" class="twitter" title="Share on Twitter" target="_blank" rel="nofollow">
      <svg class="icon">
  <use xlink:href="#twitter"></use>
</svg>
    </a>
    <a href="https://www.facebook.com/sharer.php?u=https%3a%2f%2falexzshl.gitee.io%2fblog%2fpost%2fdocker%2f&t=Docker" class="facebook" title="Share on Facebook" target="_blank" rel="nofollow">
      <svg class="icon">
  <use xlink:href="#facebook"></use>
</svg>
    </a>
    <a href="#linkedinshare" id = "linkedinshare" class="linkedin" title="Share on LinkedIn" rel="nofollow">
      <svg class="icon">
  <use xlink:href="#linkedin"></use>
</svg>
    </a>
    <a href="https://alexzshl.gitee.io/blog/post/docker/" title="Copy Link" class="link link_yank">
      <svg class="icon">
  <use xlink:href="#copy"></use>
</svg>
    </a>
  </div>

    
    
    <h2>Overview</h2>
    <nav id="TableOfContents">
  <ul>
    <li><a href="#1-docker-概述">1. Docker 概述</a>
      <ul>
        <li><a href="#docker-为什么出现">Docker 为什么出现</a></li>
        <li><a href="#docker-的历史">Docker 的历史</a></li>
        <li><a href="#docker-能干吗">Docker 能干吗</a></li>
        <li><a href="#docker-的基本组成">Docker 的基本组成</a></li>
      </ul>
    </li>
    <li><a href="#2-docker-安装">2. Docker 安装</a>
      <ul>
        <li><a href="#本地环境">本地环境</a></li>
        <li><a href="#安装">安装</a></li>
        <li><a href="#hello-world">Hello World</a></li>
        <li><a href="#底层原理">底层原理</a></li>
      </ul>
    </li>
    <li><a href="#3-docker-命令">3. Docker 命令</a>
      <ul>
        <li><a href="#帮助命令">帮助命令</a></li>
        <li><a href="#镜像命令">镜像命令</a></li>
        <li><a href="#容器命令">容器命令</a></li>
        <li><a href="#作业">作业</a></li>
        <li><a href="#可视化">可视化</a></li>
      </ul>
    </li>
    <li><a href="#4-docker-镜像详解">4. Docker 镜像详解</a>
      <ul>
        <li><a href="#41-镜像是什么">4.1. 镜像是什么</a></li>
        <li><a href="#42-docker镜像加载原理">4.2. Docker镜像加载原理</a></li>
        <li><a href="#43-分层理解">4.3. 分层理解</a></li>
        <li><a href="#44-commit-镜像">4.4. commit 镜像</a></li>
      </ul>
    </li>
    <li><a href="#5-容器数据卷">5. 容器数据卷</a>
      <ul>
        <li><a href="#51-使用数据卷">5.1. 使用数据卷</a></li>
        <li><a href="#52-具名和匿名挂载">5.2. 具名和匿名挂载</a></li>
        <li><a href="#53-数据共享">5.3. 数据共享</a></li>
      </ul>
    </li>
    <li><a href="#6-dockerfile">6. DockerFile</a>
      <ul>
        <li><a href="#初识-dockerfile">初识 DockerFile</a></li>
        <li><a href="#命令">命令</a></li>
        <li><a href="#springboot-app-镜像制作">SpringBoot App 镜像制作</a></li>
        <li><a href="#发布镜像">发布镜像</a></li>
      </ul>
    </li>
    <li><a href="#7docker-网络">7.Docker 网络</a>
      <ul>
        <li></li>
      </ul>
    </li>
    <li><a href="#8-docker-集群部署管理">8. Docker 集群部署管理</a>
      <ul>
        <li><a href="#docker-compose">Docker Compose</a></li>
        <li><a href="#cicd-之-jekins">CI/CD 之 Jekins</a></li>
      </ul>
    </li>
    <li><a href="#99-docker-常用命令">99. Docker 常用命令</a>
      <ul>
        <li><a href="#mysql">MySQL</a></li>
        <li><a href="#nginx-1">NGINX</a></li>
        <li><a href="#redis">Redis</a></li>
        <li><a href="#activemq">ActiveMQ</a></li>
        <li><a href="#bitwardenrsserver">Bitwardenrs/server</a></li>
        <li><a href="#candy">Candy</a></li>
      </ul>
    </li>
  </ul>
</nav>
    <h2 id="1-docker-概述">1. Docker 概述</h2>
<h3 id="docker-为什么出现">Docker 为什么出现</h3>
<p>例如: springboot 打包的jar包的部署,依赖于机器上的其他环境(redis, mysql, jdk, es), 而且这些环境每个都需要配置, 非常麻烦. 希望能有一种技术,将应用和环境一起打包,这样开发和生产就能无缝衔接</p>
<p>跨平台问题</p>
<p>隔离: Docker的核心思想, 每个docker镜像都是互相隔离的</p>
<h3 id="docker-的历史">Docker 的历史</h3>
<h3 id="docker-能干吗">Docker 能干吗</h3>
<h3 id="docker-的基本组成">Docker 的基本组成</h3>
<p>镜像: image</p>
<p>容器: container</p>
<p>仓库: repository</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210123111655559.png" alt="image-20210123111655559"></p>
<h2 id="2-docker-安装">2. Docker 安装</h2>
<h3 id="本地环境">本地环境</h3>
<p>Docker 最新版本只支持 Windows 10</p>
<p>如果想用 linux 学习 docker ,建议试用腾讯云 或者 阿里云的 云服务器</p>
<p><a href="https://cloud.tencent.com/act/free">https://cloud.tencent.com/act/free</a></p>
<p>连接云服务器:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-powershell" data-lang="powershell">$ ssh root@81.68.88.117
</code></pre></div><p>然后输入密码</p>
<p>另外可以通过 ssh 秘钥 登录,不需要每次输入密码</p>
<p>ssh连接软件推荐:</p>
<p>首选推荐 vscode + 插件: remote / docker</p>
<p>其他还有xshell</p>
<h3 id="安装">安装</h3>
<p>centos 7以上</p>
<p>卸载旧的docker</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">	yun remove docker <span style="color:#ae81ff">\ </span>
	&gt; docker-client <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>	&gt; docker-client-latest <span style="color:#ae81ff">\ </span>
	&gt; docker-common <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>	&gt; docker-latest <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>	&gt; docker-latest-logrotate <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>	&gt; docker-logrotate <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>	&gt; docker-engine
</code></pre></div><p>安装基本环境</p>
<p>centos</p>
<p>使用阿里云公共镜像仓库(后面会使用个人帐号镜像加速)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#75715e"># 切换到root用户(如果需要)</span>
su root

<span style="color:#75715e"># step 1: 安装必要的一些系统工具</span>
yum install -y yum-utils device-mapper-persistent-data lvm2

<span style="color:#75715e"># Step 2: 添加软件源信息, 否则安装的可能是yum官方的较旧的docker版本</span>
<span style="color:#75715e"># aliyun镜像仓库(docker-ce)</span>
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
<span style="color:#75715e"># 官方docker源</span>
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

<span style="color:#75715e"># Step 3: 更新并安装Docker-CE(即docker)</span>
yum makecache fast
yum -y install docker-ce

<span style="color:#75715e"># Step 4: 开启Docker服务</span>

<span style="color:#75715e"># 启动docker</span>
systemctl start docker
<span style="color:#75715e"># 或者 sudo service start docker</span>

<span style="color:#75715e"># 重启docker</span>
systemctl restart docker

<span style="color:#75715e"># 停止docker</span>
systemctl stop docker

<span style="color:#75715e"># 开机启动 docker deamon 守护进程</span>
systemctl enable docker

<span style="color:#75715e"># 注意：</span>
<span style="color:#75715e"># 官方软件源默认启用了最新的软件，您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用，您可以通过以下方式开启。同理可以开启各种测试版本等。</span>
<span style="color:#75715e"># vim /etc/yum.repos.d/docker-ee.repo</span>
<span style="color:#75715e">#   将[docker-ce-test]下方的enabled=0修改为enabled=1</span>
<span style="color:#75715e">#</span>
<span style="color:#75715e"># 安装指定版本的Docker-CE:</span>
<span style="color:#75715e"># Step 1: 查找Docker-CE的版本:</span>
<span style="color:#75715e"># yum list docker-ce.x86_64 --showduplicates | sort -r</span>
<span style="color:#75715e">#   Loading mirror speeds from cached hostfile</span>
<span style="color:#75715e">#   Loaded plugins: branch, fastestmirror, langpacks</span>
<span style="color:#75715e">#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            docker-ce-stable</span>
<span style="color:#75715e">#   docker-ce.x86_64            17.03.1.ce-1.el7.centos            @docker-ce-stable</span>
<span style="color:#75715e">#   docker-ce.x86_64            17.03.0.ce-1.el7.centos            docker-ce-stable</span>
<span style="color:#75715e">#   Available Packages</span>
<span style="color:#75715e"># Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)</span>
<span style="color:#75715e"># sudo yum -y install docker-ce-[VERSION]</span>

</code></pre></div><p>其他安装方式:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">curl -sSL https://get.daocloud.io/docker | sh
</code></pre></div><h3 id="hello-world">Hello World</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run hello-world
</code></pre></div><p>查看镜像</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker images
</code></pre></div><p>卸载 docker</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">yum remove docker-ce docker-ce-cli containerd.io
rm -rf /var/lib/docker
</code></pre></div><p>docker 的默认工作路径 <code>/var/lib/docker</code></p>
<h4 id="镜像加速">镜像加速</h4>
<p>阿里云个人镜像加速:</p>
<p>参考 <a href="https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors">https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors</a></p>
<p>执行以下命令修改配置文件:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <span style="color:#e6db74">&lt;&lt;-&#39;EOF&#39;
</span><span style="color:#e6db74">{
</span><span style="color:#e6db74">  &#34;registry-mirrors&#34;: [&#34;https://3kl0p8vs.mirror.aliyuncs.com&#34;]
</span><span style="color:#e6db74">}
</span><span style="color:#e6db74">EOF</span>
sudo systemctl daemon-reload
sudo systemctl restart docker
</code></pre></div><p>如果是腾讯云, 使用以下镜像路径: <code>https://mirror.ccs.tencentyun.com</code></p>
<h3 id="底层原理">底层原理</h3>
<p>docker run 过程:</p>
<ul>
<li>开始</li>
<li>docker 在本机寻找镜像 image</li>
<li>如果存在,使用这个镜像并运行</li>
<li>如果不存在,就去远程仓库寻找</li>
<li>如果远程没有,就会失败</li>
<li>如果远程有, 就会下载到本地</li>
<li>运行本地下载好的镜像</li>
</ul>
<p>docker 是一个 client-server 结构的系统, docker 的守护进程运行在主机上,通过socket从客户端访问</p>
<p>dockerServer 接收到 docker-client 的指令, 就会执行这个命令</p>
<p>dockeer 好比是一个独立的小的linux虚拟机</p>
<h2 id="3-docker-命令">3. Docker 命令</h2>
<h3 id="帮助命令">帮助命令</h3>
<p>docker version</p>
<p>docker info</p>
<p>docker</p>
<p>docker 命令 &ndash;help</p>
<p>docker &ndash;help</p>
<h3 id="镜像命令">镜像命令</h3>
<p>docker images &ndash;help</p>
<p>docker images 查看所有本地镜像</p>
<p>-a ,&ndash;all 显示所有</p>
<p>-q, &ndash;quiet 只显示镜像id</p>
<p>组合命令: docker images -aq</p>
<p>显示指定名称的镜像(即所有版本): <code>docker images mysql</code></p>
<p>过滤显示镜像列表:  <code>docker images -f &quot;dangling=true&quot;</code>,</p>
<h4 id="搜索镜像">搜索镜像</h4>
<p>docker search &ndash;help</p>
<p>docker search mysql</p>
<p>docker search mysql &ndash;filter=stars=3000</p>
<h4 id="下载镜像拉取到本地">下载镜像(拉取到本地)</h4>
<p>docker pull &ndash;help</p>
<p>docker pull mysql</p>
<p>运行结果:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#f92672">[</span>root@VM-4-8-centos ~<span style="color:#f92672">]</span><span style="color:#75715e"># docker pull mysql</span>
Using default tag: latest
latest: Pulling from library/mysql
a076a628af6f: Pull complete 
f6c208f3f991: Pull complete 
88a9455a9165: Pull complete 
406c9b8427c6: Pull complete 
7c88599c0b25: Pull complete 
25b5c6debdaf: Pull complete 
43a5816f1617: Pull complete 
1a8c919e89bf: Pull complete 
9f3cf4bd1a07: Pull complete 
80539cea118d: Pull complete 
201b3cad54ce: Pull complete 
944ba37e1c06: Pull complete 
Digest: sha256:feada149cb8ff54eade1336da7c1d080c4a1c7ed82b5e320efb5beebed85ae8c
Status: Downloaded newer image <span style="color:#66d9ef">for</span> mysql:latest
docker.io/library/mysql:latest
<span style="color:#f92672">[</span>root@VM-4-8-centos ~<span style="color:#f92672">]</span><span style="color:#75715e"># </span>

</code></pre></div><p>指定版本下载</p>
<p>docker pull mysql:5.7</p>
<h4 id="删除镜像">删除镜像</h4>
<p>删除镜像(指定image-id)</p>
<p>docker rmi -f a70d36bc331a</p>
<p>删除所有</p>
<p>docker rmi -f $(docker images -aq)</p>
<h3 id="容器命令">容器命令</h3>
<p>有了镜像才可以创建容器, 容器就是一个运行镜像的隔离的小型的虚拟OS系统</p>
<p>下载一个centos 的docker镜像</p>
<p>docker pull centos</p>
<p>运行镜像-创建容器, 同时启动并进入容器内部的centos,注意和外面的centos(真实主机/虚拟机/云虚拟主机/云服务器)不一样</p>
<p>docker run -it centos /bin/bash</p>
<p>docker run [可选参数] 镜像</p>
<p>&ndash;name=&ldquo;NAME&rdquo; 容器名字</p>
<p>-d 后台方式运行</p>
<p>-it 交互方式运行,进入容器,查看内容</p>
<p>-p 指定容器端口 -p 8080:8080</p>
<p>-p 主机端口:容器端口</p>
<p>-p 容器端口</p>
<p>-P 随机指定端口</p>
<p>退出并终止centos容器</p>
<p>exit</p>
<p>列出正在运行的容器:</p>
<p>docker ps   已经退出了,不会显示容器版centos</p>
<p>列出所有容器, 包括历史运行</p>
<p>docker ps -a</p>
<p>显示最近创建的指定数量的容器:</p>
<p>docker ps -a -n=3</p>
<p>-q 参数只显示容器编号</p>
<p>docker ps -aq</p>
<p>退出容器</p>
<p>exit 直接容器停止并退出</p>
<p>ctrl+q+q 容器不停止退出</p>
<p>删除容器:</p>
<p>docker rm 容器id (可以只输入部分字符串)</p>
<p>docker rm -f $(docker ps -aq)</p>
<p>docker ps -aq | xargs</p>
<p>启动和停止容器:</p>
<p>docker start 容器id</p>
<p>docker restart 容器id</p>
<p>docker stop 容器id</p>
<p>docker kill 容器id</p>
<p>常用其他命令:</p>
<p>后台启动</p>
<p>docker run -d centos</p>
<p>如果没有前台应用(没有对外提供服务), 启动后会直接停止</p>
<p>查看日志:</p>
<p>docker logs &ndash;help</p>
<p>首先通过centos模拟一个日志:</p>
<p>docker run -d centos /bin/sh -c &ldquo;while true;do echo alex;sleep 1;done&rdquo;</p>
<p>docker logs -f -t &ndash;tail 10 19f415469890</p>
<p>查看容器进程信息:</p>
<p>docker top &ndash;help</p>
<p>docker top</p>
<p>(important) 查看容器元数据:</p>
<p>docker inspect &ndash;help</p>
<p>docker inspect 容器ID</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">[root@VM-4-8-centos ~]# docker inspect ebac4bf86f1c
[
    {
        &#34;Id&#34;: &#34;ebac4bf86f1c40f10ecae65bf791f850a3ff142e53aa473f0a5fddf4e7a610e8&#34;,
        &#34;Created&#34;: &#34;2021-01-21T06:03:58.683490864Z&#34;,
        &#34;Path&#34;: &#34;/bin/sh&#34;,
        &#34;Args&#34;: [
            &#34;-c&#34;,
            &#34;while true;do echo alex;sleep 1;done&#34;
        ],
        &#34;State&#34;: {
            &#34;Status&#34;: &#34;running&#34;,
            &#34;Running&#34;: true,
            &#34;Paused&#34;: false,
            &#34;Restarting&#34;: false,
            &#34;OOMKilled&#34;: false,
            &#34;Dead&#34;: false,
            &#34;Pid&#34;: 19962,
            &#34;ExitCode&#34;: 0,
            &#34;Error&#34;: &#34;&#34;,
            &#34;StartedAt&#34;: &#34;2021-01-21T06:03:58.937897119Z&#34;,
            &#34;FinishedAt&#34;: &#34;0001-01-01T00:00:00Z&#34;
        },
        &#34;Image&#34;: &#34;sha256:300e315adb2f96afe5f0b2780b87f28ae95231fe3bdd1e16b9ba606307728f55&#34;,
        &#34;ResolvConfPath&#34;: &#34;/var/lib/docker/containers/ebac4bf86f1c40f10ecae65bf791f850a3ff142
        &#34;HostnamePath&#34;: &#34;/var/lib/docker/containers/ebac4bf86f1c40f10ecae65bf791f850a3ff142e5
        &#34;HostsPath&#34;: &#34;/var/lib/docker/containers/ebac4bf86f1c40f10ecae65bf791f850a3ff142e53aa
        &#34;LogPath&#34;: &#34;/var/lib/docker/containers/ebac4bf86f1c40f10ecae65bf791f850a3ff142e53aa47
        &#34;Name&#34;: &#34;/sweet_jepsen&#34;,
        &#34;RestartCount&#34;: 0,
        &#34;Driver&#34;: &#34;overlay2&#34;,
        &#34;Platform&#34;: &#34;linux&#34;,
        &#34;MountLabel&#34;: &#34;&#34;,
        &#34;ProcessLabel&#34;: &#34;&#34;,
        &#34;AppArmorProfile&#34;: &#34;&#34;,
        &#34;ExecIDs&#34;: null,
        &#34;HostConfig&#34;: {
            &#34;Binds&#34;: null,
            &#34;ContainerIDFile&#34;: &#34;&#34;,
            &#34;LogConfig&#34;: {
                &#34;Type&#34;: &#34;json-file&#34;,
                &#34;Config&#34;: {}
            },
            &#34;NetworkMode&#34;: &#34;default&#34;,
            &#34;PortBindings&#34;: {},
            &#34;RestartPolicy&#34;: {
                &#34;Name&#34;: &#34;no&#34;,
                &#34;MaximumRetryCount&#34;: 0
            },
            &#34;AutoRemove&#34;: false,
            &#34;VolumeDriver&#34;: &#34;&#34;,
            &#34;VolumesFrom&#34;: null,
            &#34;CapAdd&#34;: null,
            &#34;CapDrop&#34;: null,
            &#34;CgroupnsMode&#34;: &#34;host&#34;,
            &#34;Dns&#34;: [],
            &#34;DnsOptions&#34;: [],
            &#34;DnsSearch&#34;: [],
            &#34;ExtraHosts&#34;: null,
            &#34;GroupAdd&#34;: null,
            &#34;IpcMode&#34;: &#34;private&#34;,
            &#34;Cgroup&#34;: &#34;&#34;,
            &#34;Links&#34;: null,
            &#34;OomScoreAdj&#34;: 0,
            &#34;PidMode&#34;: &#34;&#34;,
            &#34;Privileged&#34;: false,
            &#34;PublishAllPorts&#34;: false,
            &#34;ReadonlyRootfs&#34;: false,
            &#34;SecurityOpt&#34;: null,
            &#34;UTSMode&#34;: &#34;&#34;,
            &#34;UsernsMode&#34;: &#34;&#34;,
            &#34;ShmSize&#34;: 67108864,
            &#34;Runtime&#34;: &#34;runc&#34;,
            &#34;ConsoleSize&#34;: [
                0,
                0
            ],
            &#34;Isolation&#34;: &#34;&#34;,
            &#34;CpuShares&#34;: 0,
            &#34;Memory&#34;: 0,
            &#34;NanoCpus&#34;: 0,
            &#34;CgroupParent&#34;: &#34;&#34;,
            &#34;BlkioWeight&#34;: 0,
            &#34;BlkioWeightDevice&#34;: [],
            &#34;BlkioDeviceReadBps&#34;: null,
            &#34;BlkioDeviceWriteBps&#34;: null,
            &#34;BlkioDeviceReadIOps&#34;: null,
            &#34;BlkioDeviceWriteIOps&#34;: null,
            &#34;CpuPeriod&#34;: 0,
            &#34;CpuQuota&#34;: 0,
            &#34;CpuRealtimePeriod&#34;: 0,
            &#34;CpuRealtimeRuntime&#34;: 0,
            &#34;CpusetCpus&#34;: &#34;&#34;,
            &#34;CpusetMems&#34;: &#34;&#34;,
            &#34;Devices&#34;: [],
            &#34;DeviceCgroupRules&#34;: null,
            &#34;DeviceRequests&#34;: null,
            &#34;KernelMemory&#34;: 0,
            &#34;KernelMemoryTCP&#34;: 0,
            &#34;MemoryReservation&#34;: 0,
            &#34;MemorySwap&#34;: 0,
            &#34;MemorySwappiness&#34;: null,
            &#34;OomKillDisable&#34;: false,
            &#34;PidsLimit&#34;: null,
            &#34;Ulimits&#34;: null,
            &#34;CpuCount&#34;: 0,
            &#34;CpuPercent&#34;: 0,
            &#34;IOMaximumIOps&#34;: 0,
            &#34;IOMaximumBandwidth&#34;: 0,
            &#34;MaskedPaths&#34;: [
                &#34;/proc/asound&#34;,
                &#34;/proc/acpi&#34;,
                &#34;/proc/kcore&#34;,
                &#34;/proc/keys&#34;,
                &#34;/proc/latency_stats&#34;,
                &#34;/proc/timer_list&#34;,
                &#34;/proc/timer_stats&#34;,
                &#34;/proc/sched_debug&#34;,
                &#34;/proc/scsi&#34;,
                &#34;/sys/firmware&#34;
            ],
            &#34;ReadonlyPaths&#34;: [
                &#34;/proc/bus&#34;,
                &#34;/proc/fs&#34;,
                &#34;/proc/irq&#34;,
                &#34;/proc/sys&#34;,
                &#34;/proc/sysrq-trigger&#34;
            ]
        },
        &#34;GraphDriver&#34;: {
            &#34;Data&#34;: {
                &#34;LowerDir&#34;: &#34;/var/lib/docker/overlay2/6a962ae11db0bda2764deb30b81c0188260f2eb2342bfcd06659c2970806b9980e/diff&#34;,
                &#34;MergedDir&#34;: &#34;/var/lib/docker/overlay2/6a962ae11db0bda2764deb30b81c0188260f2e
                &#34;UpperDir&#34;: &#34;/var/lib/docker/overlay2/6a962ae11db0bda2764deb30b81c0188260f2eb
                &#34;WorkDir&#34;: &#34;/var/lib/docker/overlay2/6a962ae11db0bda2764deb30b81c0188260f2eb2
            },
            &#34;Name&#34;: &#34;overlay2&#34;
        },
        &#34;Mounts&#34;: [],
        &#34;Config&#34;: {
            &#34;Hostname&#34;: &#34;ebac4bf86f1c&#34;,
            &#34;Domainname&#34;: &#34;&#34;,
            &#34;User&#34;: &#34;&#34;,
            &#34;AttachStdin&#34;: false,
            &#34;AttachStdout&#34;: false,
            &#34;AttachStderr&#34;: false,
            &#34;Tty&#34;: false,
            &#34;OpenStdin&#34;: false,
            &#34;StdinOnce&#34;: false,
            &#34;Env&#34;: [
                &#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&#34;
            ],
            &#34;Cmd&#34;: [
                &#34;/bin/sh&#34;,
                &#34;-c&#34;,
                &#34;while true;do echo alex;sleep 1;done&#34;
            ],
            &#34;Image&#34;: &#34;centos&#34;,
            &#34;Volumes&#34;: null,
            &#34;WorkingDir&#34;: &#34;&#34;,
            &#34;Entrypoint&#34;: null,
            &#34;OnBuild&#34;: null,
            &#34;Labels&#34;: {
                &#34;org.label-schema.build-date&#34;: &#34;20201204&#34;,
                &#34;org.label-schema.license&#34;: &#34;GPLv2&#34;,
                &#34;org.label-schema.name&#34;: &#34;CentOS Base Image&#34;,
                &#34;org.label-schema.schema-version&#34;: &#34;1.0&#34;,
                &#34;org.label-schema.vendor&#34;: &#34;CentOS&#34;
            }
        },
        &#34;NetworkSettings&#34;: {
            &#34;Bridge&#34;: &#34;&#34;,
            &#34;SandboxID&#34;: &#34;3b2b590a7895feb67e389c995d4816b5287bfea9bdf607b530e6333db59bbd60&#34;,
            &#34;HairpinMode&#34;: false,
            &#34;LinkLocalIPv6Address&#34;: &#34;&#34;,
            &#34;LinkLocalIPv6PrefixLen&#34;: 0,
            &#34;Ports&#34;: {},
            &#34;SandboxKey&#34;: &#34;/var/run/docker/netns/3b2b590a7895&#34;,
            &#34;SecondaryIPAddresses&#34;: null,
            &#34;SecondaryIPv6Addresses&#34;: null,
            &#34;EndpointID&#34;: &#34;5b607a9dead7ea8c263d9ae1840fc0bff90f6d98d0ed4f2e5e0fa5627fd68e35&#34;,
            &#34;Gateway&#34;: &#34;172.17.0.1&#34;,
            &#34;GlobalIPv6Address&#34;: &#34;&#34;,
            &#34;GlobalIPv6PrefixLen&#34;: 0,
            &#34;IPAddress&#34;: &#34;172.17.0.2&#34;,
            &#34;IPPrefixLen&#34;: 16,
            &#34;IPv6Gateway&#34;: &#34;&#34;,
            &#34;MacAddress&#34;: &#34;02:42:ac:11:00:02&#34;,
            &#34;Networks&#34;: {
                &#34;bridge&#34;: {
                    &#34;IPAMConfig&#34;: null,
                    &#34;Links&#34;: null,
                    &#34;Aliases&#34;: null,
                    &#34;NetworkID&#34;: &#34;3521479c165988bc68471ffdf8b2d7e3f608c226af76c425703b6dbf8bf
                    &#34;EndpointID&#34;: &#34;5b607a9dead7ea8c263d9ae1840fc0bff90f6d98d0ed4f2e5e0fa5627f
                    &#34;Gateway&#34;: &#34;172.17.0.1&#34;,
                    &#34;IPAddress&#34;: &#34;172.17.0.2&#34;,
                    &#34;IPPrefixLen&#34;: 16,
                    &#34;IPv6Gateway&#34;: &#34;&#34;,
                    &#34;GlobalIPv6Address&#34;: &#34;&#34;,
                    &#34;GlobalIPv6PrefixLen&#34;: 0,
                    &#34;MacAddress&#34;: &#34;02:42:ac:11:00:02&#34;,
                    &#34;DriverOpts&#34;: null
                }
            }
        }
    }
]
</code></pre></div><p>(important) 进入正在运行的容器:</p>
<p>打开一个新的centos bash窗口</p>
<p>docker exec it 容器id bashshell</p>
<p>例如: docker exec -it ebac4bf86f1c /bin/bash</p>
<p>进入centos容器当前shell窗口</p>
<p>docker attach 容器id</p>
<p>从容器拷贝文件到主机</p>
<p>docker cp 容器id:容器内路径 目的主机路径</p>
<p>例如: docker cp 356f30b22174:/home/alex.json /home</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210121231731197.png" alt="image-20210121142640466"></p>
<h3 id="作业">作业</h3>
<h4 id="nginx">nginx</h4>
<p>下载镜像</p>
<p>docker pull nginx</p>
<p>创建容器: 容器内镜像nginx以80端口启动,映射到宿主3344端口</p>
<p>docker run -d &ndash;name nginx01 -p 3344:80 nginx</p>
<p>curl localhost:3344</p>
<p>localhost:3344 能访问的前提是在ssh登录后的控制台界面, 另外需要看看云服务控制台防火墙是否需要开放3344端口:</p>
<p>remote:3344 -&gt; docker:nginx01:3344</p>
<p>如果使用 vscode remote 连接ssh更加方便, 因为vscode帮再次帮我们映射端口,从而可以在本地通过浏览器访问远程服务器的3344端口(即使远程服务器没有开放端口),也就是3次映射:</p>
<p>本地:3344 -&gt; remote:3344 -&gt; docker:nginx01:3344</p>
<p>vscode remote 是一个神器, 使得我们能够通过友好的windows界面来进行基于远程服务器的开发, remote插件的体验几乎就是完美地融入了远程服务器,我们几乎感受不到远程服务器的存在,仿佛我们的本地计算机就是远程服务器一样</p>
<p>其他人想访问这个页面,可以访问云服务器的公网ip+端口(请替换为自己的云服务器地址):http://81.68.88.117:3344/</p>
<p>停止容器:</p>
<p>docker stop nginx01</p>
<p>启动容器</p>
<p>docker start nginx01</p>
<p>进入容器</p>
<p>docker exec -it nginx01 /bin/bash</p>
<p>whereis nginx</p>
<p>cd /etc/nginx</p>
<p>引出问题: 每次改动容器内nginx配置文件,都需要进入容器内部?十分麻烦,要是能够在外部直接管理内部文件就好了.</p>
<h4 id="tomcat">tomcat</h4>
<p>用完即删: docker run -it &ndash;rm tomcat:9.0</p>
<p>docker pull tomcat</p>
<p>docker run -dp 3355:8080 &ndash;name tomcat01 tomcat</p>
<p>访问3355端口会报404,页面找不到,但是说明服务器已经启动了. 其实 docker 的 tomcat 是一个阉割版</p>
<p>docker exec -it tomcat01 /bin/bash</p>
<p>ls -al 查看文件</p>
<p>cd webapps 空的目录</p>
<p>原因: 阿里云默认是最小可运行的环境</p>
<p>cp -r webapps.dist/* webapps</p>
<p>再次引出问题: 项目要部署到容器内部,如果每次都要进入容器配置就十分麻烦, 要是有一种技术可以将容器内的路径映射到外部,例如将webapps映射到外部就好了</p>
<h4 id="es--kibanaocker-run--d---name-elasticsearch---net-somenetwork--p-92009200--p-93009300--e-discoverytypesingle-node-elasticsearchtag">es / kibanaocker run -d &ndash;name elasticsearch &ndash;net somenetwork -p 9200:9200 -p 9300:9300 -e &ldquo;discovery.type=single-node&rdquo; elasticsearch:tag</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d --name es01 -p 9200:9200 -p 9300:9300 -e <span style="color:#e6db74">&#34;discovery.type=single-node&#34;</span> elasticsearch:7.6.2
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#75715e"># 完整版</span>
$ docker network create somenetwork
$ docker run -d --name elasticsearch --net somenetwork -p 9200:9200 -p 9300:9300 -e <span style="color:#e6db74">&#34;discovery.type=single-node&#34;</span> elasticsearch:7.6.2
</code></pre></div><p>es 启动后非常卡, 默认占用1g内存左右, 如果云服务器配置太低可能根本不允许启动这个进程,你将不会看到es docker 容器在运行</p>
<p>查看容器性能: docker stats</p>
<p>-e 参数就是配置es环境参数</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d --name es01 -p 9200:9200 -p 9300:9300 -e <span style="color:#e6db74">&#34;discovery.type=single-node&#34;</span> -e ES_JAVA_OPTS<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;-Xms64m -Xmx512m&#34;</span> elasticsearch:7.6.2
</code></pre></div><p>引出问题: 如果启动一个kibana容器,那么kibana如何访问es?直接访问端口是不行的,因为kibana现在和es位于两个不同的docker 容器, 而docker 容器之间是相互隔离的. 既然无法通信,那么就需要宿主机来为两个docker容器进行中转. 需要 docker network 的支持</p>
<h3 id="可视化">可视化</h3>
<p>即类似kibana那样的一种web管理控制台</p>
<h4 id="portainer">portainer</h4>
<p>图形化界面管理工具</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d -p 8088:9000 --restart<span style="color:#f92672">=</span>always -v /var/run/docker.sock:/var/run/docker.sock --privileged<span style="color:#f92672">=</span>true portainer/portainer
</code></pre></div><p>然后打开浏览器: http://81.68.88.117:8088/  如果无法访问,注意配置云服务器防火墙规则</p>
<p>如果使用 vscode-remote: http://localhost:8088/ 或者根据弹出的提示打开浏览器</p>
<p>平时不会使用这个</p>
<h4 id="rancher">Rancher</h4>
<h2 id="4-docker-镜像详解">4. Docker 镜像详解</h2>
<h3 id="41-镜像是什么">4.1. 镜像是什么</h3>
<p>轻量级的,可执行的独立软件包,用来打包软件运行环境和基于运行环境开发的软件,它包含某个软件所需的所有内容,包括:代码,运行时,库,环境变量和配置文件等</p>
<p>来源:</p>
<ul>
<li>远程仓库下载</li>
<li>别人拷贝</li>
<li>自己制作 (Dockerfile)</li>
</ul>
<h3 id="42-docker镜像加载原理">4.2. Docker镜像加载原理</h3>
<p>UnionFS (联合文件系统)</p>
<p>docker 容器(视为一个小型精简的linux系统)是秒级启动, 而传统的虚拟机是分钟级启动</p>
<p>Docker镜像加载原理</p>
<h3 id="43-分层理解">4.3. 分层理解</h3>
<p>docker 的分层,如果其他image已经下载了需要的层,就不需要再下载了</p>
<p>以下是下载一个 redis 的log:</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210121142640466.png" alt="image-20210121231731197"></p>
<p>从上面可以看到有一条是: already exists, 前面的id就是一个&quot;层&quot;, 这个层已经被其他image下载过了,如果是一个全新安装的docker,显然所有的层都需要下载</p>
<p>docker 镜像都是只读的, 当容器启动时, 一个新的可写层被加载到镜像的顶部!这一层就是我们通常的容器层, 容器之下的都叫镜像层</p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210122163053870.png" alt="image-20210122000203671"></p>
<p>那么如何提交一个自己的镜像</p>
<h3 id="44-commit-镜像">4.4. commit 镜像</h3>
<p>docker commit 提交当前容器快照成为一个新的副本(image)</p>
<p>docker commit -m=&quot;[description]&quot; -a=&ldquo;author&rdquo; container_id 目标镜像名:[TAG]</p>
<p>实例:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker commit -a<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;alex&#34;</span> -m<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;add webapps app&#34;</span> tomcat01 tomcat02:1.0.0

docker run -dp 8080:8080 --name tomcat02 tomcat02:1.0.0
</code></pre></div><h2 id="5-容器数据卷">5. 容器数据卷</h2>
<p>将容器内部的目录映射至宿主机的一个目录</p>
<p>容器之间可以有一个数据共享的技术, Docker 容器中产生的数据, 同步到本地, 就不会丢失</p>
<p>这就是卷技术! 目录的挂载, 将我们容器内的目录, 挂载到 linux 上面</p>
<p>总结: 容器的持久化和同步操作! 容器之间也是可以数据共享的</p>
<h3 id="51-使用数据卷">5.1. 使用数据卷</h3>
<p>使用命令  <code>-v 主机目录:容器内目录</code></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">docker run -dp 8080:8080 --name centos01 -v /home/volumes/centos01/data:/home centos
docker inspect centos01
</code></pre></div><p>原理: <strong>当使用<code>-v</code>参数时，镜像目录下的任何文件都不会被复制到Volume中。（译者注：Volume会复制到镜像目录，镜像不会复制到卷）</strong></p>
<p>也就是当使用 <code>... run -v ...</code> 时, 宿主机的数据volume会复制到镜像目录, 而镜像不会复制到volume. 后续的增/删/改 操作则是双向同步的</p>
<p>宿主机类目录移动,映射依然会保持, 双向绑定, 使用到了linux的link技术</p>
<p>挂载之后,需要消耗双倍的硬盘空间</p>
<p>如果删除了容器, 挂载的目录下的数据并不会被删除</p>
<p>挂载 centos 下的 nginx 资源目录:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -dp 3344:80 -v /home/volumes/nginx01/data:/usr/share/nginx --name nginx01 nginx
</code></pre></div><h4 id="实战-mysql">实战 MySQL</h4>
<p>安装mysql:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker pull mysql:5.7
docker images mysql
</code></pre></div><p>简单的启动一个mysql实例:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run --name mysql99 -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123</span> -d mysql:5.7
</code></pre></div><p>启动mysql + 映射路径:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -dp 3406:3306 -v /home/volumes/mysql/conf:/etc/mysql/conf.d -v /home/volumes/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> --name mysql mysql:5.7
</code></pre></div><p>启动成功之后用navcat等软件连接数据库: 81.68.88.117 3406 root 123456</p>
<p>删除容器, 宿主机中挂载的数据卷依然存在</p>
<h3 id="52-具名和匿名挂载">5.2. 具名和匿名挂载</h3>
<p>如果-v使用 <code>宿主机绝对路径:容器路径</code>形式, 生成的卷其实是匿名的,即没有为这个卷指定一个友好的名字</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d -P -v /home/xxxx:/etc/nginx --name nginx11 --rm nginx
docker volume ls
</code></pre></div><p>如果-v使用 <code>卷名:容器路径</code>形式, 生成的卷名字就是name, 不过此时并没有指定宿主机挂载的路径, docker 会将目录挂载到默认的卷路径下面:</p>
<p><code>/var/lib/docker/volumes/{具名卷}/_data</code></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d -P -v xxxx:/etc/nginx --name nginx12 --rm nginx
docker volume ls
</code></pre></div><div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#75715e"># 查看卷信息</span>
➜  ~ docker volume inspect xxxx                                          
<span style="color:#f92672">[</span>
    <span style="color:#f92672">{</span>
        <span style="color:#e6db74">&#34;CreatedAt&#34;</span>: <span style="color:#e6db74">&#34;2021-01-22T14:33:10+08:00&#34;</span>,
        <span style="color:#e6db74">&#34;Driver&#34;</span>: <span style="color:#e6db74">&#34;local&#34;</span>,
        <span style="color:#e6db74">&#34;Labels&#34;</span>: null,
        <span style="color:#e6db74">&#34;Mountpoint&#34;</span>: <span style="color:#e6db74">&#34;/var/lib/docker/volumes/xxxx/_data&#34;</span>,
        <span style="color:#e6db74">&#34;Name&#34;</span>: <span style="color:#e6db74">&#34;xxxx&#34;</span>,
        <span style="color:#e6db74">&#34;Options&#34;</span>: null,
        <span style="color:#e6db74">&#34;Scope&#34;</span>: <span style="color:#e6db74">&#34;local&#34;</span>
    <span style="color:#f92672">}</span>
<span style="color:#f92672">]</span>
➜  ~ docker volume inspect 68e02b1b7b5fd217edd92e9b21ac3fbf7b50e1716dc9c874501c196f02214708   
<span style="color:#f92672">[</span>
    <span style="color:#f92672">{</span>
        <span style="color:#e6db74">&#34;CreatedAt&#34;</span>: <span style="color:#e6db74">&#34;2021-01-22T13:26:50+08:00&#34;</span>,
        <span style="color:#e6db74">&#34;Driver&#34;</span>: <span style="color:#e6db74">&#34;local&#34;</span>,
        <span style="color:#e6db74">&#34;Labels&#34;</span>: null,
        <span style="color:#e6db74">&#34;Mountpoint&#34;</span>: <span style="color:#e6db74">&#34;/var/lib/docker/volumes/68e02b1b7b5fd217edd92e9b21ac3fbf7b50e1716dc9c874501c196f02214708/_data&#34;</span>,
        <span style="color:#e6db74">&#34;Name&#34;</span>: <span style="color:#e6db74">&#34;68e02b1b7b5fd217edd92e9b21ac3fbf7b50e1716dc9c874501c196f02214708&#34;</span>,
        <span style="color:#e6db74">&#34;Options&#34;</span>: null,
        <span style="color:#e6db74">&#34;Scope&#34;</span>: <span style="color:#e6db74">&#34;local&#34;</span>
    <span style="color:#f92672">}</span>
<span style="color:#f92672">]</span>
➜  ~ ls /var/lib/docker/volumes 
68e02b1b7b5fd217edd92e9b21ac3fbf7b50e1716dc9c874501c196f02214708  backingFsBlockDev
70729c8b2655c22918192b95bd899d3a961ef796f7e1a9a954b7e428eccd70ab  ce821344b101011e31903d2b197a57d12962e867002b13255efa1496f47598f4
78be69dfd5e6e077c4399efa42f1211b2045cca08adb0307fbf1932208c3aeec  metadata.db
8275ae4fd2a95ce193530779b79a53ea148bc05399d55f2231f76821f3606179  xxxx
➜  ~ 
</code></pre></div><p>如果-v直接使用 <code>容器路径</code>形式(没有<code>:</code>,只有容器路径),结果同上,也是使用默认路径, 只是生成的卷名字是匿名的</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d -P -v /home/xxxx:/etc/nginx --name nginx13 --rm nginx
docker volume ls
</code></pre></div><p>通过具名挂载,可以方便使用我们的卷</p>
<p>指定容器目录的读写权限:</p>
<p><code>docker run -d -P -v xxxx:/etc/nginx:ro --name nginx12 --rm nginx</code></p>
<p><code>ro</code>: readonly 容器内部是只读权限,只能通过宿主机来写数据到容器</p>
<p><code>rw</code>:read and write 默认是rw</p>
<h3 id="53-数据共享">5.3. 数据共享</h3>
<p>如果要授权一个容器访问(严格来说是直接使用另一个容器的mount配置)另一个容器的Volume，我们可以使用<code>-volumes-from</code>参数来执行<code>docker run</code></p>
<p>使用参数 <code>--volumes-from</code>, 新建的容器将使用目标容器相同的挂载点, 实现多个容器的数据共享. 通过<code>docker inspect 容器</code>比较多个容器的挂载点可以发现它们使用的是同一个挂载点,也就是多个容器的卷挂载在宿主机的同一个路径, 对宿主机的任何数据操作/任何容器的卷数据操作,在所有容器上都是同步的</p>
<p>关键的一点: 删除任何容器,不会影响其他的容器,因为宿主机的挂载路径内数据是不会受到影响的(<code>Linux 硬链接</code>)</p>
<p>而增删文件的操作是同步的</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -it --volumes-from c1 --name c2 centos:alez
</code></pre></div><p>用途: 多个 mysql  redis  实现数据共享</p>
<p>结论: 容器之间配置信息的传递</p>
<h2 id="6-dockerfile">6. DockerFile</h2>
<h3 id="初识-dockerfile">初识 DockerFile</h3>
<p>dockerfile 就是用来构建 docker 镜像的构建文件</p>
<p>脚本就是一个一个的命令, 每个命令(每行)都是一层(<code>layer</code>)</p>
<p><code>docker build -t nginx:v3 .</code></p>
<p>如果 构建文件名称 不是标准名称,可以使用 -f 参数指定:</p>
<p><code>docker build -f {dockerfile-name} -t nginx:v3 .</code></p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210122000203671.png" alt="image-20210122163053870"></p>
<h3 id="命令">命令</h3>
<p>基础知识:</p>
<ol>
<li>
<p>每个保留关键字(指令)都必须是大写字母</p>
</li>
<li>
<p>执行重上到下的顺序</p>
</li>
<li>
<p><code>＃</code> 表示注释</p>
</li>
<li>
<p>各一个指令都会创建一个新的<code>layer</code>并提交</p>
</li>
</ol>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210122163429090.png" alt="image-20210122163429090"></p>
<p><code>dockerfile</code> 是面向开发的, 我们以后发布项目, 作镜像, 就需要编写 <code>dockerfile</code>文件, 这个文件十分简单!</p>
<p>传统的开发是将 jar 包转交给测试或者运维, 使用docker以后就是将docker镜像发布给他们</p>
<p>Docker 镜像就是包含了我们的jar包和所需的运行环境</p>
<p>Docker 镜像逐渐成为了企业交付的标准, 必须要掌握!</p>
<p>Docker 三大件:</p>
<ul>
<li>DockerFile : 构建文件, 定义了一切的步骤, 源代码</li>
<li>Image: 通过DockerFile构建生成的镜像, 最终发布和运行的产品(原来是jar/war包)</li>
<li>Container: 容器就是镜像运行起来提供服务器(端口映射)</li>
</ul>
<h4 id="dockerfile-指令">DockerFile 指令</h4>
<p>基础指令:</p>
<ul>
<li><code>FROM</code> 基础镜像, 一切从这里开始, 最基础的镜像是 scratch(几十k左右)</li>
<li><code>MAINTAINER</code> 镜像是谁写的, 姓名 + 邮箱</li>
<li><code>RUN</code> 镜像构建过程中需要运行的命令</li>
<li><code>ADD</code> 添加依赖文件, 例如tomcat压缩包</li>
<li><code>WORKDIR</code> 镜像的工作目录</li>
<li><code>VOLUME</code> 挂载的目录(不存在会新建)</li>
<li><code>EXPOSE</code> 指定需要暴露的端口(否则启动镜像时用<code>run -p</code>指定)</li>
<li><code>CMD</code> 容器启动时需要执行的命令. 只有最后一个会生效而且可被替代(docker 的<code>run</code>中指定了命令就会替换)</li>
<li><code>ENTRYPOINT</code> 容器启动时需要执行的命令, 可以追加命令(run 追加)</li>
<li><code>ONBUILD</code> 当构建一个被继承的 dockerfile 这个时候就会触发这个指令</li>
<li><code>COPY</code> 类似add, 但是是将文件拷贝到镜像中</li>
<li><code>ENV</code> 构建时设置环境变量</li>
</ul>
<p>编写 dockerfile</p>
<p><code>build -t centos:v1</code></p>
<p><code>docker history centos:v1</code></p>
<h3 id="springboot-app-镜像制作">SpringBoot App 镜像制作</h3>
<p>用springboot写一个简单的helloworld, 默认为8080端口</p>
<p>用 lifecycle:package打包为jar包<code>xxx.jar</code></p>
<p>编写dockerfile:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dockerfile" data-lang="dockerfile"><span style="color:#66d9ef">FROM</span><span style="color:#e6db74"> java:8</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">VOLUME</span><span style="color:#e6db74"> /tmp</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">ADD</span> app.jar app.jar<span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">RUN</span> bash -c <span style="color:#e6db74">&#39;touch /app.jar&#39;</span><span style="color:#960050;background-color:#1e0010">
</span><span style="color:#960050;background-color:#1e0010"></span><span style="color:#66d9ef">ENTRYPOINT</span> [<span style="color:#e6db74">&#34;java&#34;</span>,<span style="color:#e6db74">&#34;-Djava.security.egd=file:/dev/./urandom&#34;</span>,<span style="color:#e6db74">&#34;-jar&#34;</span>,<span style="color:#e6db74">&#34;/app.jar&#34;</span>]<span style="color:#960050;background-color:#1e0010">
</span></code></pre></div><p>打包镜像运行:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker build -t app:1.0
docker run -dp 9090:8080 --name app app:1.0
</code></pre></div><p>云服务器应用访问地址:</p>
<p><a href="81.68.88.117:9090/person">tencent</a></p>
<p><a href="http://47.115.139.117:9090/person">aliyun</a></p>
<h3 id="发布镜像">发布镜像</h3>
<h4 id="dockerhub">Dockerhub</h4>
<p>account: alexzshl zd823~</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker login
<span style="color:#75715e"># 根据提示输入用户名密码登录 ...</span>

<span style="color:#75715e"># 给本地镜像打上标记, 必须符合 `用户名/仓库名`</span>
docker tag app:1.0 alexzshl/app-springboot-01:1.0

<span style="color:#75715e"># push</span>
docker push alexzshl/app-springboot-01:1.0
</code></pre></div><p>关于tag: <code>docker tag source target</code>可以将某个镜像重新打上标记,其实是引用那个镜像id并且重命名一个合适的 <code>repo:tag</code>, 同一个 <code>image id</code>可以有多个<code>repo:tag</code>, 如果使用<code>docker rmi xxx</code> 后面跟的是image-id时,所有的repo:tag都会删除,所以此时不允许删除,必须加上 <code>-f</code>参数强制删除所有tags, 如果只想删除某个tag, 就不要指定image-id, 而是指定<code>repo:tag</code>, 即<code>docker rmi repo:tag</code></p>
<h4 id="发布到-aliyun-镜像">发布到 aliyun 镜像</h4>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">$ sudo docker login --username<span style="color:#f92672">=</span>alex_zen registry.cn-hangzhou.aliyuncs.com
$ sudo docker pull registry.cn-hangzhou.aliyuncs.com/alexzshl/app-springboot-01:<span style="color:#f92672">[</span>镜像版本号<span style="color:#f92672">]</span>
$ sudo docker login --username<span style="color:#f92672">=</span>alex_zen registry.cn-hangzhou.aliyuncs.com
$ sudo docker tag <span style="color:#f92672">[</span>ImageId<span style="color:#f92672">]</span> registry.cn-hangzhou.aliyuncs.com/alexzshl/app-springboot-01:<span style="color:#f92672">[</span>镜像版本号<span style="color:#f92672">]</span>
$ sudo docker push registry.cn-hangzhou.aliyuncs.com/alexzshl/app-springboot-01:<span style="color:#f92672">[</span>镜像版本号<span style="color:#f92672">]</span>
</code></pre></div><h2 id="7docker-网络">7.Docker 网络</h2>
<p>Docker 网络</p>
<p>通过 <code>ip addr</code> 可以看到一个网络名称 <code>docker0</code></p>
<ul>
<li>
<p>lo: 回环子网</p>
</li>
<li>
<p>eth0: 局域网, 即云服务器分配的内网地址</p>
</li>
<li>
<p>docker0 : docker 默认网卡, 如果run时不使用 &ndash;net指定 br-xxx网络,则新建的容器默认分配此网段地址</p>
</li>
<li>
<p>br-xxx : docker 新建的子网,用于子网隔离, <code>docker network create somenetwork</code></p>
<p><img src="https://gitee.com/alexzshl/picbed/raw/master/image-20210123130639354.png" alt="image-20210123130639354"></p>
</li>
<li>
<p>veth&hellip; : 每新建一个容器, 宿主机就会创建一个用于桥接的网卡</p>
</li>
</ul>
<p>docker 容器启动时会自动创建一个由docker分配的网络配置: eth0</p>
<p>宿主机可以直接ping同容器内的ip地址</p>
<p>容器之间也可以ping通</p>
<p>宿主机docker相当于创建了一个路由器, docker0相当于网关</p>
<p>docker0: 172.17.0.1</p>
<p>容器的ip: 172.17.0.x</p>
<p>使用的是桥接模式 evth-pair</p>
<p>每启动一个容器, 宿主和容器会分别创建一个对应的网卡, 这就是桥接模式</p>
<p>docker network 操作:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#75715e"># docker network --help</span>

<span style="color:#75715e"># docker 新建 network (全写)</span>
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 test01

<span style="color:#75715e"># docker 新建 network (简写)</span>
docker network create --subnet 192.168.0.0/16 test01

<span style="color:#75715e"># docker 查看 network 列表</span>
docker network ls

<span style="color:#75715e"># docker 查看 指定 network 详情</span>
docker network inspect test01

docker run -d -P --name tomcat-net-01 --net test01 --rm tomcat
docker run -d -P --name tomcat-net-02 --net test01 --rm tomcat

docker exec -it tomcat-net-01 ping tomcat-net-02

docker run -d -P --name tomcat-net-03 --rm tomcat
docker network connect test01 tomcat-net-03
docker network ls
docker exec -it tomcat-net-01 ping tomcat-net-03
docker exec -it tomcat-net-03 ip addr

docker stop <span style="color:#66d9ef">$(</span>docker ps -q<span style="color:#66d9ef">)</span>
</code></pre></div><p>将某个容器连接另一个网络:</p>
<p><code>docker network connect 网络名 容器名</code></p>
<p>连接之后, 会将容器直接放到 指定网络下, 这时候就相当于为那个容器分配了两个网段的ip</p>
<h4 id="实战-部署redis集群">实战: 部署redis集群</h4>
<p>运行以下redis集群配置脚本 <code>redis-conf.sh</code></p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#66d9ef">for</span> port in <span style="color:#66d9ef">$(</span>seq <span style="color:#ae81ff">1</span> 6<span style="color:#66d9ef">)</span>; <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span><span style="color:#66d9ef">do</span> <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>mkdir -p /mydata/redis/node-<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span>/conf
touch /mydata/redis/node-<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span>/conf/redis.conf
cat <span style="color:#e6db74">&lt;&lt;EOF &gt;/mydata/redis/node-${port}/conf/redis.conf
</span><span style="color:#e6db74">port 6379
</span><span style="color:#e6db74">bind 0.0.0.0
</span><span style="color:#e6db74">cluster-enabled yes
</span><span style="color:#e6db74">cluster-config-file nodes.conf
</span><span style="color:#e6db74">cluster-node-timeout 5000
</span><span style="color:#e6db74">cluster-announce-ip 172.38.0.1${port}
</span><span style="color:#e6db74">cluster-announce-port 6379
</span><span style="color:#e6db74">cluster-announce-bus-port 16379
</span><span style="color:#e6db74">appendonly yes
</span><span style="color:#e6db74">EOF</span>
<span style="color:#66d9ef">done</span>
</code></pre></div><p>创建docker network:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker network create --subnet 172.38.0.0/16 redis
</code></pre></div><p>编写脚本启动6个redis服务:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#66d9ef">for</span> port in <span style="color:#66d9ef">$(</span>seq <span style="color:#ae81ff">1</span> 6<span style="color:#66d9ef">)</span>
<span style="color:#66d9ef">do</span>
docker run <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>-d <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>-p 637<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span>:6379 <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>-p 1637<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span>:16379 <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>--name redis-<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span> <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>-v /mydata/redis/node-<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span>/data:/data <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>-v /mydata/redis/node-<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span>/conf/redis.conf:/etc/redis/redis.conf <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>--net redis --ip 172.38.0.1<span style="color:#e6db74">${</span>port<span style="color:#e6db74">}</span> <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>redis:5.0.9-alpine3.11 <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>redis-server /etc/redis/redis.conf
<span style="color:#66d9ef">done</span>
</code></pre></div><p>附-启动单个redis-server的命令:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -d -p 6371:6379 -p 16371:16379 --name redis-1 -v /mydata/redis/node-1/data:/data -v /mydata/redis/node-1/conf/redis.conf:/etc/redis/redis.conf --net redis --ip 172.38.0.11 redis:5.0.9-alpine3.11 redis-server /etc/redis/redis.conf
</code></pre></div><p>设置redis集群(先在服务器上安装本地redis):</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas <span style="color:#ae81ff">1</span>
</code></pre></div><p>连接redis:</p>
<p>redis-cli -c -h 172.38.0.11 -p 6379</p>
<p>查看信息: <code>cluster info </code> <code>cluster nodes</code></p>
<p>操作记录:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">/data <span style="color:#75715e"># redis-cli -c</span>
127.0.0.1:6379&gt; cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:8
cluster_my_epoch:1
cluster_stats_messages_ping_sent:181
cluster_stats_messages_pong_sent:178
cluster_stats_messages_sent:359
cluster_stats_messages_ping_received:178
cluster_stats_messages_pong_received:181
cluster_stats_messages_received:359
127.0.0.1:6379&gt; 
127.0.0.1:6379&gt; cluster nodes
54b78d1ee93b2dc9d94a895a4ff15c3a1c4cce0c 172.38.0.13:6379@16379 slave 0300553e54b331709925e414e195c7156e00f80e <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393018583</span> <span style="color:#ae81ff">8</span> connected
0300553e54b331709925e414e195c7156e00f80e 172.38.0.14:6379@16379 master - <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393017000</span> <span style="color:#ae81ff">8</span> connected 10923-16383
378e4afcdcb332202ef7da7b953ad03922c69796 172.38.0.15:6379@16379 slave 56e5cef6a20f7ce5e718bd36da5099329c38ce2f <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393017580</span> <span style="color:#ae81ff">5</span> connected
4ee441b5afda7e09b7d9a2ffd4a8fe8a5a5c8bc6 172.38.0.12:6379@16379 master - <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393018583</span> <span style="color:#ae81ff">2</span> connected 5461-10922
d0ac51a4d660e0ff04589546f6bafd7138da9ef0 172.38.0.16:6379@16379 slave 4ee441b5afda7e09b7d9a2ffd4a8fe8a5a5c8bc6 <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393017580</span> <span style="color:#ae81ff">6</span> connected
56e5cef6a20f7ce5e718bd36da5099329c38ce2f 172.38.0.11:6379@16379 myself,master - <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393017000</span> <span style="color:#ae81ff">1</span> connected 0-5460
127.0.0.1:6379&gt; 
127.0.0.1:6379&gt; set a <span style="color:#ae81ff">11111111111111</span>
-&gt; Redirected to slot <span style="color:#f92672">[</span>15495<span style="color:#f92672">]</span> located at 172.38.0.14:6379
OK
172.38.0.14:6379&gt; set b <span style="color:#ae81ff">2222222222</span>
-&gt; Redirected to slot <span style="color:#f92672">[</span>3300<span style="color:#f92672">]</span> located at 172.38.0.11:6379
OK
172.38.0.11:6379&gt; set c <span style="color:#ae81ff">222222222222222222</span>
-&gt; Redirected to slot <span style="color:#f92672">[</span>7365<span style="color:#f92672">]</span> located at 172.38.0.12:6379
OK
172.38.0.12:6379&gt; set d <span style="color:#ae81ff">5555555555</span>
-&gt; Redirected to slot <span style="color:#f92672">[</span>11298<span style="color:#f92672">]</span> located at 172.38.0.14:6379
OK
172.38.0.14:6379&gt; get a
<span style="color:#e6db74">&#34;11111111111111&#34;</span>
172.38.0.14:6379&gt; get b
-&gt; Redirected to slot <span style="color:#f92672">[</span>3300<span style="color:#f92672">]</span> located at 172.38.0.11:6379
<span style="color:#e6db74">&#34;2222222222&#34;</span>
172.38.0.11:6379&gt; get c
-&gt; Redirected to slot <span style="color:#f92672">[</span>7365<span style="color:#f92672">]</span> located at 172.38.0.12:6379
<span style="color:#e6db74">&#34;222222222222222222&#34;</span>
172.38.0.12:6379&gt; get d
-&gt; Redirected to slot <span style="color:#f92672">[</span>11298<span style="color:#f92672">]</span> located at 172.38.0.14:6379
<span style="color:#e6db74">&#34;5555555555&#34;</span>
172.38.0.14:6379&gt; 
</code></pre></div><p>如果停止当前的redis组服务器redis-2: <code>docker stop redis-2</code></p>
<p>slave<code>redis-4</code>会顶上成为master</p>
<p>操作记录:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">172.38.0.14:6379&gt; cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:9
cluster_my_epoch:8
cluster_stats_messages_ping_sent:811
cluster_stats_messages_pong_sent:803
cluster_stats_messages_fail_sent:5
cluster_stats_messages_auth-ack_sent:1
cluster_stats_messages_sent:1620
cluster_stats_messages_ping_received:803
cluster_stats_messages_pong_received:806
cluster_stats_messages_fail_received:1
cluster_stats_messages_auth-req_received:1
cluster_stats_messages_received:1611
172.38.0.14:6379&gt; cluster nodes
0300553e54b331709925e414e195c7156e00f80e 172.38.0.14:6379@16379 myself,master - <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393358000</span> <span style="color:#ae81ff">8</span> connected 10923-16383
54b78d1ee93b2dc9d94a895a4ff15c3a1c4cce0c 172.38.0.13:6379@16379 slave 0300553e54b331709925e414e195c7156e00f80e <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393359000</span> <span style="color:#ae81ff">8</span> connected
378e4afcdcb332202ef7da7b953ad03922c69796 172.38.0.15:6379@16379 slave 56e5cef6a20f7ce5e718bd36da5099329c38ce2f <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393359344</span> <span style="color:#ae81ff">5</span> connected
d0ac51a4d660e0ff04589546f6bafd7138da9ef0 172.38.0.16:6379@16379 master - <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393360345</span> <span style="color:#ae81ff">9</span> connected 5461-10922
56e5cef6a20f7ce5e718bd36da5099329c38ce2f 172.38.0.11:6379@16379 master - <span style="color:#ae81ff">0</span> <span style="color:#ae81ff">1611393360000</span> <span style="color:#ae81ff">1</span> connected 0-5460
4ee441b5afda7e09b7d9a2ffd4a8fe8a5a5c8bc6 172.38.0.12:6379@16379 master,fail - <span style="color:#ae81ff">1611393329881</span> <span style="color:#ae81ff">1611393328779</span> <span style="color:#ae81ff">2</span> connected
172.38.0.14:6379&gt; 
</code></pre></div><h4 id="实战-部署-springboot-微服务">实战: 部署 springboot 微服务</h4>
<p>流程:</p>
<ol>
<li>maven打包 springboot 项目为 jar 包</li>
<li>编写 dockerfile</li>
<li>制作image</li>
<li>启动容器</li>
</ol>
<p>curl localhost:49163</p>
<h2 id="8-docker-集群部署管理">8. Docker 集群部署管理</h2>
<h3 id="docker-compose">Docker Compose</h3>
<p>dockerfile</p>
<p>docker-compose.yml</p>
<p>docker-compose up/down</p>
<p>Compose概念:</p>
<ul>
<li>service: 容器,应用 web/redis/tomcat</li>
<li>project: 一组关联的容器</li>
</ul>
<p>安装:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">sudo curl -L <span style="color:#e6db74">&#34;https://github.com/docker/compose/releases/download/1.28.0/docker-compose-</span><span style="color:#66d9ef">$(</span>uname -s<span style="color:#66d9ef">)</span><span style="color:#e6db74">-</span><span style="color:#66d9ef">$(</span>uname -m<span style="color:#66d9ef">)</span><span style="color:#e6db74">&#34;</span> -o /usr/local/bin/docker-compose
</code></pre></div><p>上面的下载速度太慢, 其他可用安装方式(国内地址)</p>
<pre><code>curl -L https://get.daocloud.io/docker/compose/releases/download/1.28.0/docker-compose-`uname -s`-`uname -m` &gt; /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
</code></pre><p>卸载(删除文件夹即可)</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">sudo rm /usr/local/bin/docker-compose
</code></pre></div><p>Docker Swarm</p>
<p>集群方式部署</p>
<h3 id="cicd-之-jekins">CI/CD 之 Jekins</h3>
<h2 id="99-docker-常用命令">99. Docker 常用命令</h2>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker search java

docker pull centos
docker pull centos:7
docker pull java
docker pull java:8
docker images
docker images -aq
docker images java
docker rmi java:8
docker rmi 7878r4fgdf5gf7d
docker rmi <span style="color:#66d9ef">$(</span>docker images -aq<span style="color:#66d9ef">)</span>
docker rmi <span style="color:#66d9ef">$(</span>docker images java -aq<span style="color:#66d9ef">)</span>

docker run -it --name test java:8 /bin/bash
docker run -it --name test java:8 sh
docker ps -aq
docker ps -aq
docker exec -it test sh
docker attach test
docker stop test
docker start test
docker rm test
docker rm <span style="color:#66d9ef">$(</span>docker ps -aq<span style="color:#66d9ef">)</span>

docker login
docker logout
docker tag java:8 alexzshl/java:8
docker push alexzshl/java:8
</code></pre></div><h3 id="mysql">MySQL</h3>
<p>简单的 mysql 容器</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> -dp 3306:3306 --name mysql mysql:5.7
</code></pre></div><p>正式的 mysql 容器</p>
<p>从5.7.18开始官方不再二进制包中提供my-default.cnf文件</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker pull mysql:5.7
docker pull mysql

<span style="color:#75715e"># 创建临时 mysql 容器</span>
docker run --rm --name mysql_temp -it -v /usr/local/docker/mysql/conf:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> mysql:5.7 /bin/bash

<span style="color:#75715e"># 容器内拷贝mysql配置文件到映射目录</span>
ls /etc/mysql/
cp /etc/mysql/my.cnf /var/lib/mysql
cp -R /etc/mysql/conf.d/ /var/lib/mysql/conf.d
cp -R /etc/mysql/mysql.conf.d/ /var/lib/mysql/mysql.conf.d
exit
cd /usr/local/docker/mysql/conf
ls

<span style="color:#75715e"># 创建正式的mysql容器</span>
docker run --name mysql_std -d -p 3307:3306 -v /usr/local/docker/mysql/conf:/etc/mysql -v /usr/local/docker/mysql/logs:/var/log/mysql -v /usr/local/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> mysql:5.7

<span style="color:#75715e"># 没有 cnf 文件映射的配置</span>
docker run --name mysql_env -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> -d mysql:5.7 --character-set-server<span style="color:#f92672">=</span>utf8mb4 --collation-server<span style="color:#f92672">=</span>utf8mb4_unicode_ci

docker exec -it mysql bash
docker exec -it mysql_std bash
</code></pre></div><p>docker 模拟 mysql 主从</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell"><span style="color:#75715e"># 准备 master</span>
docker run --rm --name mysql_temp -it -v /usr/local/docker/mysql-cluster/mysql-master/conf:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> mysql:5.7 /bin/bash
ls /etc/mysql/
cp /etc/mysql/my.cnf /var/lib/mysql
cp -R /etc/mysql/conf.d/ /var/lib/mysql/conf.d
cp -R /etc/mysql/mysql.conf.d/ /var/lib/mysql/mysql.conf.d

<span style="color:#75715e"># 准备 slave01</span>
docker run --rm --name mysql_temp -it -v /usr/local/docker/mysql-cluster/mysql-slave01/conf:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> mysql:5.7 /bin/bash
ls /etc/mysql/
cp /etc/mysql/my.cnf /var/lib/mysql
cp -R /etc/mysql/conf.d/ /var/lib/mysql/conf.d
cp -R /etc/mysql/mysql.conf.d/ /var/lib/mysql/mysql.conf.d

<span style="color:#75715e"># 创建 master</span>
docker run --name mysql-master -d -p 3401:3306 -v /usr/local/docker/mysql-cluster/mysql-master/conf:/etc/mysql -v /usr/local/docker/mysql-cluster/mysql-master/logs:/var/log/mysql -v /usr/local/docker/mysql-cluster/mysql-master/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> mysql:5.7

<span style="color:#75715e"># 创建 slave01</span>
docker run --name mysql-slave01 -d -p 3402:3306 -v /usr/local/docker/mysql-cluster/mysql-slave01/conf:/etc/mysql -v /usr/local/docker/mysql-cluster/mysql-slave01/logs:/var/log/mysql -v /usr/local/docker/mysql-cluster/mysql-slave01/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span> mysql:5.7

docker stop mysql-master
docker rm mysql-master

docker stop mysql-slave01
docker rm mysql-slave01
</code></pre></div><p>修改配置文件</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">vim /usr/local/docker/mysql-cluster/mysql-master/conf/mysql.conf.d/mysqld.cnf

server-id<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>
log-bin<span style="color:#f92672">=</span>/var/lib/mysql/mysql-bin



vim /usr/local/docker/mysql-cluster/mysql-slave01/conf/mysql.conf.d/mysqld.cnf

server-id<span style="color:#f92672">=</span><span style="color:#ae81ff">2</span>
</code></pre></div><h3 id="nginx-1">NGINX</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker run --name some-nginx -v /some/content:/usr/share/nginx/html:ro -d nginx

docker run --name some-nginx -d -p 8080:80 some-content-nginx
</code></pre></div><h3 id="redis">Redis</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker pull redis
docker pull redis:6
docker pull redis:6.2
docker pull redis:6.2.1

docker run -d --name redis redis
docker run -d -p 6379:6379 --name redis redis
docker run -itd --name redis-test -p 6379:6379 redis
docker run --name redis -d redis redis-server --appendonly yes
docker run -dp 6379:6379 -v /docker/host/dir:/data --name redis redis redis-server --appendonly yes
docker run -itd --name redis-demo redis --requirepass<span style="color:#f92672">=</span><span style="color:#ae81ff">123456</span>

<span style="color:#75715e"># aliyun</span>
docker run -dp 6379:6379 -v /mydata/redis/single/data:/data --name redis redis
docker run -dp 6379:6379 -v /mydata/redis/single/data:/data --name redis redis redis-server --appendonly yes
docker exec -it redis /bin/bash


docker run -it --network some-network --rm redis redis-cli -h some-redis

docker run -v /myredis/conf:/usr/local/etc/redis --name myredis redis redis-server /usr/local/etc/redis/redis.conf



docker run -itd -p 6379:6379 -v /mydata/redis/single/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /mydata/redis/single/data:/data --name redis -e <span style="color:#e6db74">&#34;TZ=Asia/Shanghai&#34;</span> redis redis-server /usr/local/etc/redis/redis.conf

docker run -itd -p 6379:6379 -v /mydata/redis/single/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /mydata/redis/single/data:/data --name redis -e <span style="color:#e6db74">&#34;TZ=Asia/Shanghai&#34;</span> redis redis-server /usr/local/etc/redis/redis.conf --appendonly yes
</code></pre></div><p>redis.conf</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-ini" data-lang="ini"><span style="color:#a6e22e">**#redis开启守护进程，需要注释掉，不然容器无法跑起来**</span>
<span style="color:#75715e">#daemonize yes</span>
<span style="color:#a6e22e">dir /data</span>
<span style="color:#a6e22e">logfile /data/redis.log</span>
<span style="color:#a6e22e">protected-mode no</span>
<span style="color:#75715e">#注释掉，可以远程访问</span>
<span style="color:#75715e">#bind 127.0.0.1</span>
<span style="color:#75715e">#开启AOF</span>
<span style="color:#a6e22e">appendonly yes</span>
</code></pre></div><h3 id="activemq">ActiveMQ</h3>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker pull rmohr/activemq

docker run -d -p 61616:61616 -p 8161:8161 --name activemq rmohr/activemq

docker run -p 61616:61616 -p 8161:8161 <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>           -v /your/persistent/dir/conf:/opt/activemq/conf <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>           -v /your/persistent/dir/data:/opt/activemq/data <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>           rmohr/activemq
</code></pre></div><p>http://47.115.139.117:8161/admin/ admin admin</p>
<h3 id="bitwardenrsserver">Bitwardenrs/server</h3>
<p>启动一个本地 bitwarden 服务器</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker pull bitwardenrs/server:latest

docker run -d --name bitwarden -v /bw-data/:/data/ -p 80:80 bitwardenrs/server:latest

<span style="color:#75715e"># 推荐</span>
docker run -dp 12001:80  --name bitwarden bitwardenrs/server:latest

</code></pre></div><p><a href="http://alex.sas">http://alex.sas</a>:12001/</p>
<h3 id="candy">Candy</h3>
<p>web server 类似于 nginx, 支持反向代理和自动https</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-shell" data-lang="shell">docker pull candy

echo <span style="color:#e6db74">&#34;hello world&#34;</span> &gt; ~/web/hello/index.html

docker run -d -p 80:80 -v ~/web/hello/index.html:/usr/share/caddy/index.html -v /mydata/caddy/data:/data -v /mydata/caddy/config/Caddyfile:/etc/caddy/Caddyfile --name caddy caddy

docker run -d -p 80:80 -p 443:443 -v /mydata/caddy/site:/srv -v ~/web/hello/index.html:/usr/share/caddy/index.html -v /mydata/caddy/data:/data -v /mydata/caddy/config/Caddyfile:/etc/caddy/Caddyfile --name caddy caddy

<span style="color:#75715e"># 启用 https 参考示例</span>
docker run -d -p 80:80 -p 443:443 <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>    -v /site:/srv <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>    -v caddy_data:/data <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>    -v caddy_config:/config <span style="color:#ae81ff">\
</span><span style="color:#ae81ff"></span>    caddy caddy file-server --domain example.com
</code></pre></div>
    
      
    
  </article>
<aside class="sidebar">
  <section class="sidebar_inner">
    
    <h2 class="mt-4">Featured Posts</h2>
    <ul>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E7%99%BB%E5%BD%95%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/" class="nav-link">Java登录技术总结</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E5%90%8E%E7%AB%AF%E6%95%B4%E5%90%88%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD/" class="nav-link">Java后端整合微信登录功能</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/termux/" class="nav-link">Termux</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/activemq/" class="nav-link">ActiveMQ</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/bitwarden/" class="nav-link">Bitwarden</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/centos7/" class="nav-link">CentOS_7</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/idea%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/" class="nav-link">Idea使用技巧积累</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E7%B1%BB%E5%BA%93-jackson/" class="nav-link">Java类库-Jackson</a>
      </li>
    </ul>
    <h2 class="mt-4">Recent Posts</h2>
    <ul class="flex-column">
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E7%99%BB%E5%BD%95%E6%8A%80%E6%9C%AF%E6%80%BB%E7%BB%93/" class="nav-link">Java登录技术总结</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E5%90%8E%E7%AB%AF%E6%95%B4%E5%90%88%E5%BE%AE%E4%BF%A1%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD/" class="nav-link">Java后端整合微信登录功能</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/termux/" class="nav-link">Termux</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/activemq/" class="nav-link">ActiveMQ</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/bitwarden/" class="nav-link">Bitwarden</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/centos7/" class="nav-link">CentOS_7</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/idea%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/" class="nav-link">Idea使用技巧积累</a>
      </li>
      <li>
        <a href="https://alexzshl.gitee.io/blog/post/java%E7%B1%BB%E5%BA%93-jackson/" class="nav-link">Java类库-Jackson</a>
      </li>
    </ul>
    <div>
      <h2 class="mt-4 taxonomy" id="categories-section">Categories</h2>
      <nav class="tags_nav">
        <a href='https://alexzshl.gitee.io/blog/categories/java/' class="post_tag button button_translucent">
          JAVA
          <span class="button_tally">12</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/linux/' class="post_tag button button_translucent">
          LINUX
          <span class="button_tally">3</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/spring/' class="post_tag button button_translucent">
          SPRING
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/tool/' class="post_tag button button_translucent">
          TOOL
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/web/' class="post_tag button button_translucent">
          WEB
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/book/' class="post_tag button button_translucent">
          BOOK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/centos/' class="post_tag button button_translucent">
          CENTOS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/database/' class="post_tag button button_translucent">
          DATABASE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/devops/' class="post_tag button button_translucent">
          DEVOPS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/docker/' class="post_tag button button_translucent">
          DOCKER
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/framework/' class="post_tag button button_translucent">
          FRAMEWORK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/ide/' class="post_tag button button_translucent">
          IDE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/idea/' class="post_tag button button_translucent">
          IDEA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/internet/' class="post_tag button button_translucent">
          INTERNET
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/javascript-framework/' class="post_tag button button_translucent">
          JAVASCRIPT-FRAMEWORK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/json/' class="post_tag button button_translucent">
          JSON
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/lib/' class="post_tag button button_translucent">
          LIB
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/login/' class="post_tag button button_translucent">
          LOGIN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/maven/' class="post_tag button button_translucent">
          MAVEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/messaging/' class="post_tag button button_translucent">
          MESSAGING
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/mysql/' class="post_tag button button_translucent">
          MYSQL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/orm/' class="post_tag button button_translucent">
          ORM
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/security/' class="post_tag button button_translucent">
          SECURITY
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springboot/' class="post_tag button button_translucent">
          SPRINGBOOT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springcloud/' class="post_tag button button_translucent">
          SPRINGCLOUD
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springdata/' class="post_tag button button_translucent">
          SPRINGDATA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/springmvc/' class="post_tag button button_translucent">
          SPRINGMVC
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/ssh/' class="post_tag button button_translucent">
          SSH
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/terminal/' class="post_tag button button_translucent">
          TERMINAL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/categories/web-framework/' class="post_tag button button_translucent">
          WEB-FRAMEWORK
          <span class="button_tally">1</span>
        </a>
        
        
      </nav>
    </div>
    <div>
      <h2 class="mt-4 taxonomy" id="tags-section">Tags</h2>
      <nav class="tags_nav">
        <a href='https://alexzshl.gitee.io/blog/tags/activemq/' class="post_tag button button_translucent">
          ACTIVEMQ
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/docker/' class="post_tag button button_translucent">
          DOCKER
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/elasticsearch/' class="post_tag button button_translucent">
          ELASTICSEARCH
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/git/' class="post_tag button button_translucent">
          GIT
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/login/' class="post_tag button button_translucent">
          LOGIN
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/maven/' class="post_tag button button_translucent">
          MAVEN
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/mysql/' class="post_tag button button_translucent">
          MYSQL
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/redis/' class="post_tag button button_translucent">
          REDIS
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh/' class="post_tag button button_translucent">
          SSH
          <span class="button_tally">2</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/404/' class="post_tag button button_translucent">
          404
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/aka.ms/' class="post_tag button button_translucent">
          AKA.MS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/authorized_keys/' class="post_tag button button_translucent">
          AUTHORIZED_KEYS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/bitwarden/' class="post_tag button button_translucent">
          BITWARDEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/centos/' class="post_tag button button_translucent">
          CENTOS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/consul/' class="post_tag button button_translucent">
          CONSUL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/debug/' class="post_tag button button_translucent">
          DEBUG
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/design-pattern/' class="post_tag button button_translucent">
          DESIGN-PATTERN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/docker-compose/' class="post_tag button button_translucent">
          DOCKER-COMPOSE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/effective-java/' class="post_tag button button_translucent">
          EFFECTIVE-JAVA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/eureka/' class="post_tag button button_translucent">
          EUREKA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/feign/' class="post_tag button button_translucent">
          FEIGN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/fish/' class="post_tag button button_translucent">
          FISH
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/gateway/' class="post_tag button button_translucent">
          GATEWAY
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/google/' class="post_tag button button_translucent">
          GOOGLE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/hibernate/' class="post_tag button button_translucent">
          HIBERNATE
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/hystrix/' class="post_tag button button_translucent">
          HYSTRIX
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/interface-document/' class="post_tag button button_translucent">
          INTERFACE-DOCUMENT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/jackson/' class="post_tag button button_translucent">
          JACKSON
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/jpa/' class="post_tag button button_translucent">
          JPA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/json/' class="post_tag button button_translucent">
          JSON
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/jsr-107/' class="post_tag button button_translucent">
          JSR-107
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/keygen/' class="post_tag button button_translucent">
          KEYGEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/messaging/' class="post_tag button button_translucent">
          MESSAGING
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/microsoft/' class="post_tag button button_translucent">
          MICROSOFT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/nacos/' class="post_tag button button_translucent">
          NACOS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/nginx/' class="post_tag button button_translucent">
          NGINX
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/npm/' class="post_tag button button_translucent">
          NPM
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/rsa/' class="post_tag button button_translucent">
          RSA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/security/' class="post_tag button button_translucent">
          SECURITY
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/shell/' class="post_tag button button_translucent">
          SHELL
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/springcloud-alibaba/' class="post_tag button button_translucent">
          SPRINGCLOUD-ALIBABA
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/springmvc/' class="post_tag button button_translucent">
          SPRINGMVC
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh-add/' class="post_tag button button_translucent">
          SSH-ADD
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh-agent/' class="post_tag button button_translucent">
          SSH-AGENT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/ssh-keygen/' class="post_tag button button_translucent">
          SSH-KEYGEN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/stackoverflow/' class="post_tag button button_translucent">
          STACKOVERFLOW
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/swagger/' class="post_tag button button_translucent">
          SWAGGER
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/task/' class="post_tag button button_translucent">
          TASK
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/tencent-cloud/' class="post_tag button button_translucent">
          TENCENT-CLOUD
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/termux/' class="post_tag button button_translucent">
          TERMUX
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/vue.js/' class="post_tag button button_translucent">
          VUE.JS
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/vue.js-2/' class="post_tag button button_translucent">
          VUE.JS-2
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/web/' class="post_tag button button_translucent">
          WEB
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/wechat/' class="post_tag button button_translucent">
          WECHAT
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/weixin/' class="post_tag button button_translucent">
          WEIXIN
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/yum/' class="post_tag button button_translucent">
          YUM
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/zookeeper/' class="post_tag button button_translucent">
          ZOOKEEPER
          <span class="button_tally">1</span>
        </a>
        
        <a href='https://alexzshl.gitee.io/blog/tags/zsh/' class="post_tag button button_translucent">
          ZSH
          <span class="button_tally">1</span>
        </a>
        
        
      </nav>
    </div>
  </section>
</aside>

</div>
    </main><svg width="0" height="0" class="hidden">
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="facebook">
    <path d="M437 0H75C33.648 0 0 33.648 0 75v362c0 41.352 33.648 75 75 75h151V331h-60v-90h60v-61c0-49.629 40.371-90 90-90h91v90h-91v61h91l-15 90h-76v181h121c41.352 0 75-33.648 75-75V75c0-41.352-33.648-75-75-75zm0 0"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18.001 18.001" id="twitter">
    <path d="M15.891 4.013c.808-.496 1.343-1.173 1.605-2.034a8.68 8.68 0 0 1-2.351.861c-.703-.756-1.593-1.14-2.66-1.14-1.043 0-1.924.366-2.643 1.078a3.56 3.56 0 0 0-1.076 2.605c0 .309.039.585.117.819-3.076-.105-5.622-1.381-7.628-3.837-.34.601-.51 1.213-.51 1.846 0 1.301.549 2.332 1.645 3.089-.625-.053-1.176-.211-1.645-.47 0 .929.273 1.705.82 2.388a3.623 3.623 0 0 0 2.115 1.291c-.312.08-.641.118-.979.118-.312 0-.533-.026-.664-.083.23.757.664 1.371 1.291 1.841a3.652 3.652 0 0 0 2.152.743C4.148 14.173 2.625 14.69.902 14.69c-.422 0-.721-.006-.902-.038 1.697 1.102 3.586 1.649 5.676 1.649 2.139 0 4.029-.542 5.674-1.626 1.645-1.078 2.859-2.408 3.639-3.974a10.77 10.77 0 0 0 1.172-4.892v-.468a7.788 7.788 0 0 0 1.84-1.921 8.142 8.142 0 0 1-2.11.593z"
      ></path>
  </symbol>
  <symbol aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="mail">
    <path  d="M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="calendar">
    <path d="M452 40h-24V0h-40v40H124V0H84v40H60C26.916 40 0 66.916 0 100v352c0 33.084 26.916 60 60 60h392c33.084 0 60-26.916 60-60V100c0-33.084-26.916-60-60-60zm20 412c0 11.028-8.972 20-20 20H60c-11.028 0-20-8.972-20-20V188h432v264zm0-304H40v-48c0-11.028 8.972-20 20-20h24v40h40V80h264v40h40V80h24c11.028 0 20 8.972 20 20v48z"></path>
    <path d="M76 230h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zM76 310h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zM76 390h40v40H76zm80 0h40v40h-40zm80 0h40v40h-40zm80 0h40v40h-40zm80-80h40v40h-40z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="github">
    <path d="M255.968 5.329C114.624 5.329 0 120.401 0 262.353c0 113.536 73.344 209.856 175.104 243.872 12.8 2.368 17.472-5.568 17.472-12.384 0-6.112-.224-22.272-.352-43.712-71.2 15.52-86.24-34.464-86.24-34.464-11.616-29.696-28.416-37.6-28.416-37.6-23.264-15.936 1.728-15.616 1.728-15.616 25.696 1.824 39.2 26.496 39.2 26.496 22.848 39.264 59.936 27.936 74.528 21.344 2.304-16.608 8.928-27.936 16.256-34.368-56.832-6.496-116.608-28.544-116.608-127.008 0-28.064 9.984-51.008 26.368-68.992-2.656-6.496-11.424-32.64 2.496-68 0 0 21.504-6.912 70.4 26.336 20.416-5.696 42.304-8.544 64.096-8.64 21.728.128 43.648 2.944 64.096 8.672 48.864-33.248 70.336-26.336 70.336-26.336 13.952 35.392 5.184 61.504 2.56 68 16.416 17.984 26.304 40.928 26.304 68.992 0 98.72-59.84 120.448-116.864 126.816 9.184 7.936 17.376 23.616 17.376 47.584 0 34.368-.32 62.08-.32 70.496 0 6.88 4.608 14.88 17.6 12.352C438.72 472.145 512 375.857 512 262.353 512 120.401 397.376 5.329 255.968 5.329z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 212 212" id="gitlab">
    <path d="M12.3 74.7h54L43.3 3c-1-3.6-6.4-3.6-7.6 0L12.3 74.8z" />
    <path d="M12.3 74.7L.5 111c-1 3.2 0 6.8 3 8.8l101.6 74-92.5-119z"/>
    <path d="M105 193.7l-38.6-119h-54l92.7 119z"/>
    <path d="M105 193.7l38.7-119H66.4l38.7 119z"/>
    <path d="M105 193.7l38.7-119H198l-93 119z"/>
    <path d="M198 74.7l11.6 36.2c1 3 0 6.6-3 8.6l-101.5 74 93-119z"/>
    <path d="M198 74.7h-54.3L167 3c1.2-3.6 6.4-3.6 7.6 0L198 74.8z"/> 
  </symbol>
  <symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="rss">
    <circle cx="3.429" cy="20.571" r="3.429"></circle>
    <path d="M11.429 24h4.57C15.999 15.179 8.821 8.001 0 8v4.572c6.302.001 11.429 5.126 11.429 11.428z"></path>
    <path d="M24 24C24 10.766 13.234 0 0 0v4.571c10.714 0 19.43 8.714 19.43 19.429z"></path>
  </symbol>
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="linkedin">
    <path d="M437 0H75C33.648 0 0 33.648 0 75v362c0 41.352 33.648 75 75 75h362c41.352 0 75-33.648 75-75V75c0-41.352-33.648-75-75-75zM181 406h-60V196h60zm0-240h-60v-60h60zm210 240h-60V286c0-16.54-13.46-30-30-30s-30 13.46-30 30v120h-60V196h60v11.309C286.719 202.422 296.93 196 316 196c40.691.043 75 36.547 75 79.688zm0 0"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 612 612" id="arrow">
    <path d="M604.501 440.509L325.398 134.956c-5.331-5.357-12.423-7.627-19.386-7.27-6.989-.357-14.056 1.913-19.387 7.27L7.499 440.509c-9.999 10.024-9.999 26.298 0 36.323s26.223 10.024 36.222 0l262.293-287.164L568.28 476.832c9.999 10.024 26.222 10.024 36.221 0 9.999-10.023 9.999-26.298 0-36.323z"></path>
  </symbol>
  <symbol viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" id="carly">
    <path d="M504.971 239.029L448 182.059V84c0-46.317-37.682-84-84-84h-44c-13.255 0-24 10.745-24 24s10.745 24 24 24h44c19.851 0 36 16.149 36 36v108c0 6.365 2.529 12.47 7.029 16.971L454.059 256l-47.029 47.029A24.002 24.002 0 0 0 400 320v108c0 19.851-16.149 36-36 36h-44c-13.255 0-24 10.745-24 24s10.745 24 24 24h44c46.318 0 84-37.683 84-84v-98.059l56.971-56.971c9.372-9.372 9.372-24.568 0-33.941zM112 192V84c0-19.851 16.149-36 36-36h44c13.255 0 24-10.745 24-24S205.255 0 192 0h-44c-46.318 0-84 37.683-84 84v98.059l-56.971 56.97c-9.373 9.373-9.373 24.568 0 33.941L64 329.941V428c0 46.317 37.682 84 84 84h44c13.255 0 24-10.745 24-24s-10.745-24-24-24h-44c-19.851 0-36-16.149-36-36V320c0-6.365-2.529-12.47-7.029-16.971L57.941 256l47.029-47.029A24.002 24.002 0 0 0 112 192z"></path>
  </symbol>
  <symbol viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" id="copy">
    <path d="M23 2.75A2.75 2.75 0 0 0 20.25 0H8.75A2.75 2.75 0 0 0 6 2.75v13.5A2.75 2.75 0 0 0 8.75 19h11.5A2.75 2.75 0 0 0 23 16.25zM18.25 14.5h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5zm0-3h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5zm0-3h-7.5a.75.75 0 0 1 0-1.5h7.5a.75.75 0 0 1 0 1.5z"></path>
    <path d="M8.75 20.5a4.255 4.255 0 0 1-4.25-4.25V2.75c0-.086.02-.166.025-.25H3.75A2.752 2.752 0 0 0 1 5.25v16A2.752 2.752 0 0 0 3.75 24h12a2.752 2.752 0 0 0 2.75-2.75v-.75z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512.001 512.001" id="closeme">
    <path d="M284.286 256.002L506.143 34.144c7.811-7.811 7.811-20.475 0-28.285-7.811-7.81-20.475-7.811-28.285 0L256 227.717 34.143 5.859c-7.811-7.811-20.475-7.811-28.285 0-7.81 7.811-7.811 20.475 0 28.285l221.857 221.857L5.858 477.859c-7.811 7.811-7.811 20.475 0 28.285a19.938 19.938 0 0 0 14.143 5.857 19.94 19.94 0 0 0 14.143-5.857L256 284.287l221.857 221.857c3.905 3.905 9.024 5.857 14.143 5.857s10.237-1.952 14.143-5.857c7.811-7.811 7.811-20.475 0-28.285L284.286 256.002z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" id="open-menu">
    <path d="M492 236H20c-11.046 0-20 8.954-20 20s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20zm0-160H20C8.954 76 0 84.954 0 96s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20zm0 320H20c-11.046 0-20 8.954-20 20s8.954 20 20 20h472c11.046 0 20-8.954 20-20s-8.954-20-20-20z"></path>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="instagram">
    <path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id=youtube>
    <path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z"/>
  </symbol>
  <symbol xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" id="stackoverflow">
    <path d="M21 27v-8h3v11H0V19h3v8h18z"></path><path d="M17.1.2L15 1.8l7.9 10.6 2.1-1.6L17.1.2zm3.7 14.7L10.6 6.4l1.7-2 10.2 8.5-1.7 2zM7.2 12.3l12 5.6 1.1-2.4-12-5.6-1.1 2.4zm-1.8 6.8l13.56 1.96.17-2.38-13.26-2.55-.47 2.97zM19 25H5v-3h14v3z"></path>
  </symbol>
</svg>

<footer class="footer">
  <div class="footer_inner wrap pale">
    <img src='https://alexzshl.gitee.io/blog/icons/apple-touch-icon.png' class="icon icon_2 transparent">
    <p>Copyright<span class="year"></span> ALEXZSHL. All Rights Reserved</p><a class="to_top" href="#documentTop">
  <svg class="icon">
  <use xlink:href="#arrow"></use>
</svg>
</a>

  </div>
</footer>

    <script type="text/javascript" src="https://alexzshl.gitee.io/blog/js/bundle.min.16ce52f0798f54d65cefb0a0fc9228cf99e0b73de57f8a1545fe14259265bf79ba12fe15afd2fd75d5f0bff8f416e8ca8c5c3458f87e014cbfbed8ccfdaee327.js" integrity="sha512-Fs5S8HmPVNZc77Cg/JIoz5ngtz3lf4oVRf4UJZJlv3m6Ev4Vr9L9ddXwv/j0FujKjFw0WPh&#43;AUy/vtjM/a7jJw==" crossorigin="anonymous"></script>
    
  </body>
</html>
